/*
 * XmlUtil.java
 *
 * Created on 23 de Maio de 2007, 21:55
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package br.ufrj.dcc.trabxml.util;

import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.sun.org.apache.xml.internal.serialize.OutputFormat;
import com.sun.org.apache.xml.internal.serialize.XMLSerializer;

/**
 *
 * @author Artur
 */
public class XmlUtil { 
    
    
    public static boolean validate(String xml) {
        try {
            Schema s = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema").newSchema();
            Validator val = s.newValidator();
            val.validate(new StreamSource(new StringReader(xml)));
            return true;
        } catch (Exception e) {
            return false;
        }
    }
    
    public static boolean validate(String xml, String schema) {
        try {
            Schema s = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema").newSchema(new StreamSource(new StringReader(schema)));
            Validator val = s.newValidator();
            val.validate(new StreamSource(new StringReader(xml)));
            return true;
        } catch (Exception e) {
            return false;
        }
    }    
    
    public static String transformXML(String originalXML, String xslt) {
        String xml = null;
        try {
            TransformerFactory tFactory = TransformerFactory.newInstance();
            Transformer transformer = tFactory.newTransformer(new StreamSource(new StringReader(xslt)));
            transformer.setOutputProperty(javax.xml.transform.OutputKeys.METHOD, "xml");
            DOMResult domRes = new DOMResult();
            transformer.transform(new StreamSource(new StringReader(originalXML)), domRes );
            xml = prettyPrint((Document)domRes.getNode());
        } catch (Exception e) {
            e.printStackTrace();
        }
        //xml = "<mensagem/>";//para forcar erro
        return xml;
    }       
    
    public static Node getDocumentRoot(String xml) throws ParserConfigurationException, UnsupportedEncodingException, SAXException, IOException {
        Document document = getDocument(xml);
        Node node = document.getDocumentElement();
        return node;
    }

    public static Document getDocument(final String xml) throws IOException, SAXException, ParserConfigurationException, UnsupportedEncodingException {
        DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = builderFactory.newDocumentBuilder();
        Document document = builder.parse(new java.io.ByteArrayInputStream(xml.trim().getBytes("UTF8")));
        document.normalizeDocument();
        return document;
    }
    
    public static Node getElement(Node node, String name) {
        NodeList list = node.getChildNodes();
        for(int i = 0; i < list.getLength(); i++) {
            Node child = list.item(i);
            if (child.getNodeName().equals(name)) {
                return child;
            }
        }
        return node.getOwnerDocument().createElement(name);
    }
    
    public static String getElementValue(Node node, String name) {
        Node child = getElement(node,name);
        return getNodeValue(child);
    }
    
    public static Integer getElementIntegerValue(Node node, String name) {
        String value = getElementValue(node,name);
        try {
            int ret = Integer.parseInt(value);
            return ret;
        } catch (NumberFormatException ex) {
            return null;
        }
    }
    
    public static Boolean getElementBooleanValue(Node node, String name, Boolean default_value) {
        String value = getElementValue(node,name);
        if (value == null) {
            return default_value;
        }
        try {
            boolean ret = Boolean.parseBoolean(value);
            return ret;
        } catch (NumberFormatException ex) {
            return default_value;
        }
    }
    
    public static Integer getElementPercentValue(Node node, String name, Integer default_value) {
        String value = getElementValue(node,name);
        if (value == null) {
            return null;
        }
        if (!value.endsWith("%")) {
            return null;
        }
        value = value.substring(0,value.length()-1);
        try {
            int ret = Integer.parseInt(value);
            return ret;
        } catch (NumberFormatException ex) {
            return null;
        }
    }
    
    public static NodeList getElementChilds(Node node, String name) {
        Node child = getElement(node,name);
        if (child != null) {
            return child.getChildNodes();
        }
        try {
            return getDocumentRoot("<root/>").getChildNodes();
        } catch (Exception e) {
            return null;
        }
    }
    
    public static String getAttributeValue(Node node, String name) {
        Node child = node.getAttributes().getNamedItem(name);
        return getNodeValue(child);
    }
    
    public static String getNodeValue(Node child) {
        if (child != null) {
            String value = child.getTextContent();
            if (value != null) {
                value = value.trim();
                if (value.length() == 0) {
                    value = null;
                }
            }
            return value;
        }
        return null;
    }
    
    public static Node findElementByAttribute(String attr, String value, Node root) {
        if ((root == null) || (root.getAttributes() == null)) {
            return null;
        }
        if (value.equals(getAttributeValue(root,attr))) {
            return root;
        }
        NodeList list = root.getChildNodes();
        for(int i = 0; i < list.getLength(); i++) {
            Node elem = findElementByAttribute(attr,value,list.item(i));
            if (elem != null) {
                return elem;
            }
        }
        return null;
    }
    
    public static String getXmlNodeValue(String tagName, Object o) {
        if (o == null) {
            return "<"+tagName+"/>";
        }
        return "<"+tagName+">"+o.toString()+"</"+tagName+">";
    }
    
    public static String getXmlAttributeValue(String attrName, Object o) {
        if (o == null) {
            return "";
        }
        return " "+attrName+"=\""+o.toString()+"\"";
    }
    
    public static String prettyPrint(Document doc) throws IOException {
        OutputFormat format = new OutputFormat(doc);
        format.setLineWidth(65);
        format.setIndenting(true);
        format.setIndent(2);
        StringWriter writer = new StringWriter();
        XMLSerializer serializer = new XMLSerializer( writer, format);
        serializer.serialize(doc);
        return writer.getBuffer().toString();        
    }
    
    public static String prettyPrint(String xml) {
        try {
            Document doc = getDocument(xml);
            return prettyPrint(doc);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}